#pragma once
#include "Pthread.hpp"
#include <pthread.h>
#include <vector>
#include <queue>
#include <unistd.h>
#include <iostream>
#include <string>
#include <mutex>

template<class T>
class pthread_pool;

template<class T>
class pthread_data
{
public:
    pthread_pool<T>* _this;
    std::string name;
    pthread_data(pthread_pool<T>* pthis,const std::string& s)
        :_this(pthis),name(s)
    {}
};

template<class T>// 处理的任务类型
class pthread_pool
{
private:
    static void* start_routine(void* args)// 外部把任务推送给线程池，各个线程执行这个函数，在函数里面执行外部推送的任务
    {
        pthread_data<T>* td = static_cast<pthread_data<T>*>(args);
        while(true)
        {
            T t;
            {
                LockGarud lockguard(td->_this->mutex());
                while(td->_this->TaskQueueEmpty())// 没有任务就阻塞
                {
                    td->_this->CondWait();
                }
                t = td->_this->pop();
            }
            std::cout << td->name << " 获取了一个任务：" << t.send_msg() << " 结果是:" << t() << std::endl;
        }
        delete td;
        return nullptr;

    }

    pthread_pool(int size = 5)
        :_pool(size)
    {
        for(auto& e:_pool)// 构建线程对象
        {
            e = new Pthread();
        }
        pthread_mutex_init(&_lock,nullptr);
        pthread_cond_init(&_cond,nullptr);
    }
public:
    void Lock(){pthread_mutex_lock(&_lock);}
    void UnLock(){pthread_mutex_unlock(&_lock);}
    bool TaskQueueEmpty() {return _taskQueue.empty();}
    void CondWait() {pthread_cond_wait(&_cond,&_lock);}
    T pop()
    {
        T t = _taskQueue.front();
        _taskQueue.pop();
        return t;
    }

    pthread_mutex_t* mutex()
    {
        return &_lock;
    }
public:
    
    pthread_pool<T> operator=(pthread_pool<T>) = delete;
    pthread_pool(const pthread_pool<T>& pp) = delete;

    static pthread_pool<T>* getInstance(int size = 5)
    {
        // 最终线程安全版本的懒汉模式
        if(_singleton == nullptr)
        {
            _singleLock.lock();
            if(_singleton == nullptr)
            {
                _singleton = new pthread_pool<T>(size);
            }
            _singleLock.unlock();
        }
        return _singleton;
    }

    void push(const T& in)// 向进程池推送任务
    {
        LockGarud lockguard(mutex());
        _taskQueue.push(in);
        pthread_cond_signal(&_cond);
    }

    void run() // 线程池开始工作
    {
        for(auto& e:_pool)
        {
            pthread_data<T>* td = new pthread_data<T>(this,e->name());
            e->start(start_routine,td);

            // 线程池一旦开始工作，就打印这些字样
            std::cout << e->name() << " start working..." << std::endl;
        }
    }

    ~pthread_pool()
    {
        pthread_mutex_destroy(&_lock);
        pthread_cond_destroy(&_cond);
        for(const auto& e:_pool)
        {
            delete e;
        }
    }
private:
    std::vector<Pthread*> _pool;// 线程池，以数组的方式管理
    std::queue<T> _taskQueue;//任务队列
    //为了保证线程安全和没有任务时阻塞，需要提供条件变量和锁
    pthread_mutex_t _lock;
    pthread_cond_t _cond;

    // 懒汉模式
    static pthread_pool<T>* _singleton;
    static std::mutex _singleLock;
};
template<class T>
pthread_pool<T>* pthread_pool<T>::_singleton = nullptr;

template<class T>
std::mutex pthread_pool<T>::_singleLock;